#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# cron: 30 22 * * *
# new Env("顺丰速递每日统计")

import os
import re
import glob
import json
import logging
import requests
from datetime import datetime, timedelta
from collections import defaultdict

# 配置日志格式
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger("ShunFengStats")

# ====================== 配置区域 ======================
LOG_DIR_PATTERN = "/ql/data/log/XiaoMao_SFSY_renwu*"  # 日志目录模式（支持通配符）
TIME_RANGE_HOURS = 24  # 分析最近多少小时的日志
DEBUG_MODE = False      # 设置为True启用详细调试日志
REPORT_FILE = "/ql/data/log/Message/PUSH_SFSD.log"  # 报告保存路径
HONEY_ALERT_THRESHOLD = 4600  # 丰蜜提醒阈值
# =====================================================

# 在logger定义后设置调试模式
if DEBUG_MODE:
    logger.setLevel(logging.DEBUG)
    logger.debug("调试模式已启用")

def parse_sf_logs(log_content, account_data):
    """
    解析顺丰速递任务日志内容并提取统计信息
    """
    # 编译正则表达式
    account_pattern = re.compile(r'👤\s*账号\d+:【(\d{3}\*{4}\d{4})】')
    points_pattern = re.compile(r'💰\s*(?:执行前积分|当前积分)[:：]?\s*【?(\d+)】?')
    sign_in_pattern = re.compile(r'✨\s*签到成功，获得【(\d+)积分】')
    sign_fail_pattern = re.compile(r'❌\s*签到失败！原因：(.+)')
    honey_pattern = re.compile(r'🍯\s*(?:执行前丰蜜|执行后丰蜜)[:：]?\s*【?(\d+)】?')
    task_completed_pattern = re.compile(r'✨\s*【(.+?)】任务-已完成')
    task_fail_pattern = re.compile(r'❌\s*【(.+?)】任务-任务未完成')
    task_reward_pattern = re.compile(r'✨\s*【(.+?)】任务奖励领取成功！')
    
    current_account = None
    lines = log_content.split('\n')
    
    for line in lines:
        # 宽松处理空行
        if not line.strip():
            continue
            
        # 调试日志：打印处理的行
        logger.debug(f"处理行: {line}")
            
        # 检测账号
        account_match = account_pattern.search(line)
        if account_match:
            current_account = account_match.group(1)
            if current_account not in account_data:
                account_data[current_account] = {
                    'points': 0,
                    'honey': 0,
                    'sign_in': False,
                    'sign_fail_reason': None,
                    'completed_tasks': [],
                    'failed_tasks': [],
                    'rewarded_tasks': [],
                    'warnings': [],
                    'high_honey': False  # 标记丰蜜是否超过阈值
                }
            logger.debug(f"检测到账号: {current_account}")
            continue
            
        if not current_account:
            continue
            
        # 提取积分信息
        points_match = points_pattern.search(line)
        if points_match:
            points = int(points_match.group(1))
            account_data[current_account]['points'] = points
            logger.debug(f"{current_account} 积分: {points}")
            continue
            
        # 提取签到成功
        sign_in_match = sign_in_pattern.search(line)
        if sign_in_match:
            account_data[current_account]['sign_in'] = True
            logger.debug(f"{current_account} 签到成功")
            continue
            
        # 提取签到失败
        sign_fail_match = sign_fail_pattern.search(line)
        if sign_fail_match:
            reason = sign_fail_match.group(1).strip()
            account_data[current_account]['sign_fail_reason'] = reason
            account_data[current_account]['warnings'].append({
                'type': 'sign_fail',
                'message': reason
            })
            logger.debug(f"{current_account} 签到失败: {reason}")
            continue
            
        # 提取丰蜜信息
        honey_match = honey_pattern.search(line)
        if honey_match:
            honey = int(honey_match.group(1))
            account_data[current_account]['honey'] = honey
            
            # 检查是否超过阈值
            if honey > HONEY_ALERT_THRESHOLD:
                account_data[current_account]['high_honey'] = True
                logger.info(f"⚠️ 发现可兑换账号: {current_account} ({honey}丰蜜)")
            
            logger.debug(f"{current_account} 丰蜜: {honey}")
            continue
            
        # 提取已完成任务
        task_completed_match = task_completed_pattern.search(line)
        if task_completed_match:
            task_name = task_completed_match.group(1)
            if task_name not in account_data[current_account]['completed_tasks']:
                account_data[current_account]['completed_tasks'].append(task_name)
            logger.debug(f"{current_account} 任务[{task_name}]已完成")
            continue
            
        # 提取任务失败
        task_fail_match = task_fail_pattern.search(line)
        if task_fail_match:
            task_name = task_fail_match.group(1)
            if task_name not in account_data[current_account]['failed_tasks']:
                account_data[current_account]['failed_tasks'].append(task_name)
            logger.debug(f"{current_account} 任务[{task_name}]失败")
            continue
            
        # 提取任务奖励领取成功
        task_reward_match = task_reward_pattern.search(line)
        if task_reward_match:
            task_name = task_reward_match.group(1)
            if task_name not in account_data[current_account]['rewarded_tasks']:
                account_data[current_account]['rewarded_tasks'].append(task_name)
            logger.debug(f"{current_account} 任务[{task_name}]奖励领取成功")
            continue
    
    return account_data

def process_log_directories():
    """
    处理日志目录并解析所有匹配的日志文件
    返回账号统计数据
    """
    # 计算时间范围（最近N小时）
    time_threshold = datetime.now() - timedelta(hours=TIME_RANGE_HOURS)
    logger.info(f"分析时间范围: {time_threshold.strftime('%Y-%m-%d %H:%M:%S')} 至今")
    
    account_data = {}
    processed_files = 0
    skipped_files = 0
    
    # 获取所有匹配的日志文件（按时间倒序）
    all_files = []
    for log_dir in glob.glob(LOG_DIR_PATTERN):
        if not os.path.isdir(log_dir):
            continue
            
        for filename in os.listdir(log_dir):
            if filename.endswith('.log'):
                file_path = os.path.join(log_dir, filename)
                if not os.path.exists(file_path):
                    continue
                try:
                    file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
                    all_files.append((file_path, file_mtime))
                except Exception as e:
                    logger.error(f"获取文件修改时间失败: {file_path} - {str(e)}")
    
    # 按修改时间倒序排序
    all_files.sort(key=lambda x: x[1], reverse=True)
    
    # 处理日志文件
    for file_path, file_mtime in all_files:
        if file_mtime < time_threshold:
            skipped_files += 1
            logger.debug(f"跳过旧文件: {os.path.basename(file_path)} - {file_mtime}")
            continue
            
        try:
            logger.info(f"分析文件: {os.path.basename(file_path)}")
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
                account_data = parse_sf_logs(content, account_data)
                processed_files += 1
                
                # 检查数据完整性 - 如果有账号数据，继续处理更多文件
                if account_data:
                    logger.info(f"已找到 {len(account_data)} 个账号数据")
                    
        except Exception as e:
            logger.error(f"文件解析失败: {file_path} - {str(e)}")
    
    logger.info(f"文件处理完成: 已处理 {processed_files} 个文件, 跳过 {skipped_files} 个")
    return account_data

def generate_table_report(account_data):
    """生成表格格式的统计报告"""
    if not account_data:
        return "⚠️ 未找到有效的账号统计信息", {}
    
    # 计算总计
    totals = {
        'points': 0,
        'honey': 0,
        'sign_success': 0,
        'sign_fail': 0,
        'exchangeable_count': 0,
        'exchangeable_accounts': [],
        'completed_tasks': defaultdict(int),
        'rewarded_tasks': defaultdict(int),
        'failed_tasks': defaultdict(int),
        'accounts': len(account_data)
    }
    
    # 构建表格报告
    report_lines = [
        "📊 顺丰速递每日统计报告",
        "=" * 60,
        "📈 全局汇总:"
    ]
    
    # 添加全局汇总信息
    report_lines.append(f"    👥 总账号数: {len(account_data)}个")
    
    # 计算积分总计
    total_points = sum(data['points'] for data in account_data.values())
    totals['points'] = total_points
    report_lines.append(f"    💰 总积分: {total_points}")
    
    # 计算丰蜜总计
    total_honey = sum(data.get('honey', 0) for data in account_data.values())
    totals['honey'] = total_honey
    report_lines.append(f"    🍯 总丰蜜: {total_honey}")
    
    # 计算签到情况
    sign_success = sum(1 for data in account_data.values() if data.get('sign_in', False))
    sign_fail = sum(1 for data in account_data.values() if data.get('sign_fail_reason'))
    totals['sign_success'] = sign_success
    totals['sign_fail'] = sign_fail
    
    report_lines.append(f"    ✅ 签到成功: {sign_success}个")
    report_lines.append(f"    ❌ 签到失败: {sign_fail}个")
    
    # 计算可兑换账号
    exchangeable_count = 0
    exchangeable_accounts = []
    for account, data in account_data.items():
        if data.get('honey', 0) > HONEY_ALERT_THRESHOLD:
            exchangeable_count += 1
            exchangeable_accounts.append(account)
    
    totals['exchangeable_count'] = exchangeable_count
    totals['exchangeable_accounts'] = exchangeable_accounts
    
    # 添加可兑换账号信息
    report_lines.append(f"    ⚠️ 可兑换账号: {exchangeable_count}个 (丰蜜 > {HONEY_ALERT_THRESHOLD})")
    
    # 如果有可兑换账号，显示具体账号
    if exchangeable_count > 0:
        report_lines.append(f"    💡 可兑换账号: {', '.join(exchangeable_accounts)}")
        report_lines.append(f"    💡 提示: 丰蜜已超过{HONEY_ALERT_THRESHOLD}，请及时兑换!")
    
    # 计算任务统计
    for data in account_data.values():
        for task in data.get('completed_tasks', []):
            totals['completed_tasks'][task] += 1
        for task in data.get('rewarded_tasks', []):
            totals['rewarded_tasks'][task] += 1
        for task in data.get('failed_tasks', []):
            totals['failed_tasks'][task] += 1
    
    # 添加任务汇总
    if totals['completed_tasks']:
        report_lines.append("\n    📌 任务完成情况:")
        for task, count in totals['completed_tasks'].items():
            report_lines.append(f"        ✅ {task}: {count}/{len(account_data)}")
    
    if totals['rewarded_tasks']:
        report_lines.append("\n    🎁 任务奖励领取情况:")
        for task, count in totals['rewarded_tasks'].items():
            report_lines.append(f"        ✨ {task}: {count}/{len(account_data)}")
    
    if totals['failed_tasks']:
        report_lines.append("\n    ⚠️ 任务失败情况:")
        for task, count in totals['failed_tasks'].items():
            report_lines.append(f"        ❌ {task}: {count}/{len(account_data)}")
    
    report_lines.append("=" * 60)
    report_lines.append("\n📋 账号详情:")
    
    # 添加表格标题
    report_lines.append("\n账    号".ljust(20) + "积分".center(10) + "丰蜜".center(10) + "签到".center(10) + "任务".center(10))
    report_lines.append("─" * 60)
    
    # 添加每个账号的信息
    for account, data in account_data.items():
        # 格式化账号信息
        account_display = f"🔷 {account}"
        
        # 格式化积分
        points_display = f"{data['points']}".center(10)
        
        # 格式化丰蜜 - 可兑换账号添加标记
        honey_value = data.get('honey', 0)
        honey_display = f"{honey_value}"
        if data.get('high_honey', False):
            honey_display += "⭐"  # 添加可兑换标记
        honey_display = honey_display.center(10)
        
        # 格式化签到
        sign_display = "✅" if data.get('sign_in', False) else "❌"
        if data.get('sign_fail_reason'):
            sign_display = f"❌({data['sign_fail_reason'][:5]})"
        sign_display = sign_display.center(10)
        
        # 格式化任务
        completed = len(data.get('completed_tasks', []))
        total_tasks = completed + len(data.get('failed_tasks', []))
        task_display = f"{completed}/{total_tasks}".center(10)
        
        # 添加账号行
        report_lines.append(
            account_display.ljust(20) + 
            points_display + 
            honey_display + 
            sign_display + 
            task_display
        )
        
        # 添加分隔线
        report_lines.append("─" * 60)
    
    # 添加可兑换说明
    if exchangeable_count > 0:
        report_lines.append(f"    ⭐ 表示丰蜜超过{HONEY_ALERT_THRESHOLD}，可进行兑换")
    
    # 添加报告时间
    report_lines.append("=" * 60)
    report_lines.append(f"📅 报告生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    
    return "\n".join(report_lines), totals

def push_plus_notify(title, content):
    """
    使用PUSH_PLUS推送通知
    """
    token = os.environ.get('PUSH_PLUS_TOKEN')
    if not token:
        logger.error("未找到PUSH_PLUS_TOKEN环境变量，无法发送通知")
        return False
    
    try:
        # PUSH_PLUS API地址
        url = "http://www.pushplus.plus/send"
        
        # 请求数据
        data = {
            "token": token,
            "title": title,
            "content": content,
            "template": "txt"
        }
        
        # 发送请求
        response = requests.post(url, json=data)
        result = response.json()
        
        if response.status_code == 200 and result.get("code") == 200:
            logger.info("PUSH_PLUS通知发送成功")
            return True
        else:
            logger.error(f"PUSH_PLUS通知发送失败: {result.get('msg', '未知错误')}")
            return False
    except Exception as e:
        logger.error(f"发送PUSH_PLUS通知时出错: {str(e)}")
        return False

def send_notification(title, content):
    """
    发送通知
    """
    # 使用PUSH_PLUS发送通知
    if push_plus_notify(title, content):
        return True
    
    logger.warning("PUSH_PLUS通知发送失败，尝试使用其他通知方式")
    # 这里可以添加其他通知方式，如sendNotify.js
    return False

def main():
    """主函数"""
    task_start = datetime.now()
    logger.info("开始顺丰速递每日统计")
    
    try:
        # 步骤1: 处理日志目录
        account_data = process_log_directories()
        
        # 步骤2: 生成报告
        report, totals = generate_table_report(account_data)
        
        # 步骤3: 输出报告
        logger.info("\n" + report)
        
        # 步骤4: 保存报告到文件
        os.makedirs(os.path.dirname(REPORT_FILE), exist_ok=True)
        with open(REPORT_FILE, 'w', encoding='utf-8') as f:
            f.write(report)
        logger.info(f"统计报告已保存至: {REPORT_FILE}")
        
        # 步骤5: 发送通知
        if account_data:
            # 创建通知标题
            title = f"顺丰速递每日统计 ({len(account_data)}账号)"
            
            # 创建通知内容
            notify_content = [
                "📊 顺丰速递每日统计报告",
                "=" * 40,
                "📈 全局汇总:",
                f"    👥 总账号数: {len(account_data)}个",
                f"    💰 总积分: {totals['points']}",
                f"    🍯 总丰蜜: {totals['honey']}",
                f"    ✅ 签到成功: {totals['sign_success']}个",
                f"    ❌ 签到失败: {totals['sign_fail']}个",
                f"    ⚠️ 可兑换账号: {totals['exchangeable_count']}个 (丰蜜 > {HONEY_ALERT_THRESHOLD})"
            ]
            
            # 添加可兑换账号信息
            if totals['exchangeable_count'] > 0:
                notify_content.append(f"    💡 可兑换账号: {', '.join(totals['exchangeable_accounts'])}")
                notify_content.append(f"    💡 提示: 丰蜜已超过{HONEY_ALERT_THRESHOLD}，请及时兑换!")
            
            notify_content.append("=" * 40)
            notify_content.append("\n📋 账号详情:")
            
            # 添加表格标题
            notify_content.append("\n账    号".ljust(15) + "积分".center(6) + "丰蜜".center(6) + "签到".center(6) + "任务".center(8))
            notify_content.append("─" * 40)
            
            # 添加每个账号的信息
            for account, data in account_data.items():
                # 格式化账号信息
                account_display = account
                
                # 格式化积分
                points_display = f"{data['points']}".center(6)
                
                # 格式化丰蜜 - 可兑换账号添加标记
                honey_value = data.get('honey', 0)
                honey_display = f"{honey_value}"
                if data.get('high_honey', False):
                    honey_display += "⭐"  # 添加可兑换标记
                honey_display = honey_display.center(6)
                
                # 格式化签到
                sign_display = "✅" if data.get('sign_in', False) else "❌"
                if data.get('sign_fail_reason'):
                    sign_display = f"❌({data['sign_fail_reason'][:5]})"
                sign_display = sign_display.center(6)
                
                # 格式化任务
                completed = len(data.get('completed_tasks', []))
                total_tasks = completed + len(data.get('failed_tasks', []))
                task_display = f"{completed}/{total_tasks}".center(8)
                
                # 添加账号行
                notify_content.append(
                    account_display.ljust(15) + 
                    points_display + 
                    honey_display + 
                    sign_display + 
                    task_display
                )
            
            # 添加可兑换说明
            if totals['exchangeable_count'] > 0:
                notify_content.append(f"    ⭐ 表示丰蜜超过{HONEY_ALERT_THRESHOLD}，可进行兑换")
            
            # 添加报告时间
            notify_content.append("=" * 40)
            notify_content.append(f"📅 报告生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
            
            # 发送通知
            send_notification(title, "\n".join(notify_content))
        else:
            logger.warning("无有效数据，跳过通知发送")
        
        # 计算任务耗时
        task_duration = datetime.now() - task_start
        logger.info(f"任务总耗时: {task_duration.total_seconds():.2f} 秒")
        
        # 返回退出码（0表示成功）
        return 0
    except Exception as e:
        logger.exception(f"任务执行失败: {str(e)}")
        # 发送错误通知
        error_title = "顺丰速递每日统计失败"
        error_content = f"任务执行出错: {str(e)}\n\n请查看日志获取详细信息"
        send_notification(error_title, error_content)
        return 1

if __name__ == "__main__":
    import sys
    from datetime import datetime
    
    # 设置时区为北京时间
    os.environ['TZ'] = 'Asia/Shanghai'
    
    exit_code = main()
    sys.exit(exit_code)